<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="数据分析报告展示页面" />
    <meta name="author" content="Data-TK" />
    <title>数据分析报告</title>

    <!-- 引入Chart.js和Marked.js库 -->
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/marked@4.0.0/marked.min.js"></script>
    <link
      href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&family=Roboto:wght@300;400;500;700&display=swap"
      rel="stylesheet"
    />

    <style>
      /* CSS Reset */
      *,
      *::before,
      *::after {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }

      :root {
        /* Light Theme */
        --font-family-base: 'Roboto', 'Noto Sans SC', sans-serif;
        --font-family-heading: 'Roboto', 'Noto Sans SC', sans-serif;

        --bg-color: #f8f9fa;
        --bg-alt-color: #ffffff;
        --text-color: #212529;
        --text-muted-color: #6c757d;
        --primary-color: #007bff;
        --primary-hover-color: #0056b3;
        --danger-color: #dc3545;
        --border-color: #dee2e6;
        --card-bg-color: #ffffff;
        --card-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
        --card-border-radius: 12px;
        --link-color: var(--primary-color);
        --link-hover-color: var(--primary-hover-color);

        --toc-bg-color: rgba(255, 255, 255, 0.97);
        --toc-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        --toc-border-color: var(--border-color);
        --toc-active-bg: rgba(0, 123, 255, 0.08);
        --toc-active-border: var(--primary-color);

        --btn-primary-bg: var(--primary-color);
        --btn-primary-text: #ffffff;
        --btn-primary-hover-bg: var(--primary-hover-color);
        --btn-outline-border: var(--primary-color);
        --btn-outline-text: var(--primary-color);
        --btn-outline-hover-bg: rgba(0, 123, 255, 0.05);

        --primary-color-rgb: 0, 123, 255;

        /* Animation colors */
        --particle-color-1: rgba(0, 123, 255, 0.3);
        --particle-color-2: rgba(87, 179, 255, 0.2);
        --particle-color-3: rgba(0, 191, 255, 0.15);
        --particle-color-4: rgba(0, 100, 180, 0.05);
        --line-color: rgba(0, 123, 255, 0.15);

        /* Word-style variables */
        --page-width: 210mm; /* A4 宽度 */
        --page-height: 297mm; /* A4 高度 */
        --page-margin: 25mm; /* 页面边距 */
        --page-bg-color: #ffffff;
        --page-shadow: none; /* 移除阴影 */
        --page-content-width: calc(var(--page-width) - (var(--page-margin) * 2));
      }

      :root.dark-theme {
        --bg-color: #121212;
        --bg-alt-color: #1e1e1e;
        --text-color: #e8eaed;
        --text-muted-color: #9aa0a6;
        --primary-color: #58a6ff;
        --primary-hover-color: #79b8ff;
        --danger-color: #f85149;
        --border-color: #30363d;
        --card-bg-color: #1c1c1c;
        --card-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
        --link-color: var(--primary-color);
        --link-hover-color: var(--primary-hover-color);

        --toc-bg-color: rgba(28, 28, 28, 0.97);
        --toc-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
        --toc-border-color: var(--border-color);
        --toc-active-bg: rgba(88, 166, 255, 0.12);
        --toc-active-border: var(--primary-color);

        --btn-primary-bg: var(--primary-color);
        --btn-primary-text: #ffffff;
        --btn-primary-hover-bg: var(--primary-hover-color);
        --btn-outline-border: var(--primary-color);
        --btn-outline-text: var(--primary-color);
        --btn-outline-hover-bg: rgba(88, 166, 255, 0.1);

        --primary-color-rgb: 88, 166, 255;

        /* Animation colors - dark theme */
        --particle-color-1: rgba(88, 166, 255, 0.35);
        --particle-color-2: rgba(134, 196, 255, 0.25);
        --particle-color-3: rgba(65, 145, 255, 0.15);
        --particle-color-4: rgba(88, 166, 255, 0.08);
        --line-color: rgba(88, 166, 255, 0.2);
      }

      html {
        font-size: 16px;
        scroll-behavior: smooth;
      }

      body {
        font-family: var(--font-family-base);
        line-height: 1.65;
        color: var(--text-color);
        background-color: var(--bg-color); /* Fallback background */
        /* Remove the gradient animation and keep solid background */
        background: var(--bg-color);
        transition:
          color 0.2s ease,
          background-color 0.2s ease;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        display: flex;
        flex-direction: column;
        min-height: 100vh;
        opacity: 1; /* 默认显示内容 */
      }
      body.content-loaded {
        opacity: 1;
        transition: opacity 0.5s ease-out;
      }

      .page-wrapper {
        display: flex;
        flex: 1;
        max-width: 1400px;
        width: 100%;
        margin: 0 auto;
        padding: 1.5rem;
      }

      /* Navigation Bar */
      nav {
        background-color: var(--card-bg-color);
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
        padding: 0.75rem 1.5rem;
        position: sticky;
        top: 0;
        z-index: 1020;
        display: flex;
        justify-content: space-between;
        align-items: center;
        border-bottom: 1px solid var(--border-color);
        transition:
          background-color 0.2s ease,
          border-color 0.2s ease;
      }
      nav .logo-area {
        font-size: 1.4rem;
        font-weight: 600;
        color: var(--primary-color);
      }
      nav .actions {
        display: flex;
        align-items: center;
      }
      nav .actions .btn:first-child {
        margin-left: 0;
      }

      /* Buttons */
      .btn {
        display: inline-flex;
        align-items: center;
        gap: 0.4em;
        font-weight: 500;
        text-align: center;
        vertical-align: middle;
        cursor: pointer;
        user-select: none;
        border: 1px solid transparent;
        padding: 0.45rem 0.9rem;
        font-size: 0.9rem;
        border-radius: 8px;
        transition: all 0.15s ease-in-out;
      }
      .btn svg {
        width: 1em;
        height: 1em;
        vertical-align: middle;
      }
      .btn-primary {
        color: var(--btn-primary-text);
        background-color: var(--btn-primary-bg);
        border-color: var(--btn-primary-bg);
      }
      .btn-primary:hover {
        background-color: var(--btn-primary-hover-bg);
        border-color: var(--btn-primary-hover-bg);
        transform: translateY(-1px);
        box-shadow: 0 2px 6px rgba(var(--primary-color-rgb), 0.25);
      }
      .btn-outline {
        color: var(--btn-outline-text);
        border-color: var(--btn-outline-border);
        background-color: transparent;
      }
      .btn-outline:hover {
        background-color: var(--btn-outline-hover-bg);
        color: var(--btn-outline-text);
      }

      /* Main Content Area */
      .main-content {
        flex: 1;
        padding-right: 1.5rem;
        min-width: 0;
      }

      /* Footer */
      /* footer CSS removed */

      /* Floating Table of Contents Container */
      .floating-toc-container {
        width: 260px;
        position: sticky;
        top: calc(var(--nav-height, 60px) + 1.5rem);
        max-height: calc(100vh - var(--nav-height, 60px) - 3rem);
        overflow-y: auto;
        padding: 1rem;
        background-color: var(--toc-bg-color);
        border-radius: var(--card-border-radius);
        box-shadow: var(--toc-shadow);
        backdrop-filter: blur(8px);
        -webkit-backdrop-filter: blur(8px);
        transition:
          background-color 0.2s ease,
          border-color 0.2s ease,
          box-shadow 0.2s ease;
      }
      .floating-toc-container.hidden-desktop {
        display: none;
      }
      .floating-toc-toggle-btn {
        display: none;
      }

      /* Theme Toggle Button */
      /* .theme-toggle-btn CSS for fixed positioning removed */
      .theme-toggle-btn-nav {
        /* Styles to make it look like other nav buttons */
        /* If it's already a .btn.btn-outline, it might inherit well */
        /* Ensure icons are visible and switch correctly */
      }
      .theme-toggle-btn-nav .icon-dark {
        /* display: none; Initially handled by initTheme */
      }
      :root.dark-theme .theme-toggle-btn-nav .icon-light {
        display: none;
      }
      :root.dark-theme .theme-toggle-btn-nav .icon-dark {
        display: inline-block; /* Corrected from block to inline-block for nav */
      }
      .theme-toggle-text {
        margin-left: 0.4em;
      }

      .sr-only {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border-width: 0;
      }

      /* Utility classes */
      .hidden {
        display: none !important;
      }

      /* Responsive adjustments for TOC */
      @media (max-width: 1023px) {
        .main-content {
          padding-right: 0;
        }
        .floating-toc-container {
          position: fixed;
          top: 0;
          right: 0;
          bottom: 0;
          height: 100vh;
          max-height: 100vh;
          width: 280px;
          transform: translateX(100%);
          transition:
            transform 0.3s ease-in-out,
            background-color 0.2s ease,
            border-color 0.2s ease;
          border-radius: 0;
          border-left: 1px solid var(--border-color);
          border-right: none;
          padding-top: 3.5rem;
          z-index: 1030;
        }
        .floating-toc-container.show {
          transform: translateX(0);
          box-shadow: -5px 0 15px rgba(0, 0, 0, 0.15);
        }
        .floating-toc-container.hidden-desktop {
          display: block;
        }

        .floating-toc-toggle-btn {
          display: flex;
          position: fixed;
          top: calc((var(--nav-height, 60px) - 40px) / 2);
          right: 1.5rem;
          z-index: 1025;
          padding: 0.45rem 0.6rem; /* Adjust padding for icon-only button */
        }
        .floating-toc-container .close-toc-btn {
          display: block;
          position: absolute;
          top: 0.75rem;
          right: 1rem;
          background: none;
          border: none;
          font-size: 1.8rem;
          line-height: 1;
          padding: 0.25rem;
          color: var(--text-muted-color);
          cursor: pointer;
        }
        .floating-toc-container .close-toc-btn:hover {
          color: var(--primary-color);
        }
      }
      @media (min-width: 1024px) {
        .floating-toc-container {
          display: block !important;
        }
        .floating-toc-toggle-btn {
          display: none !important;
        }
        .floating-toc-container .close-toc-btn {
          display: none !important;
        }
      }

      /* General styles */
      h1,
      h2,
      h3,
      h4,
      h5,
      h6 {
        font-family: var(--font-family-heading);
        font-weight: 600; /* Bolder headings */
        color: var(--text-color);
        margin-top: 1.5em;
        margin-bottom: 0.8em;
        line-height: 1.3;
      }
      h1 {
        font-size: 2.15rem;
      }
      h2 {
        font-size: 1.65rem;
      }
      h3 {
        font-size: 1.35rem;
      }
      p {
        margin-bottom: 1.1rem;
        color: var(--text-color);
      }
      a {
        color: var(--link-color);
        text-decoration: none;
        transition: color 0.15s ease;
      }
      a:hover {
        color: var(--link-hover-color);
        text-decoration: underline;
      }

      /* Report Sections as Cards */
      .report-section-card {
        background-color: var(--card-bg-color);
        border-radius: var(--card-border-radius);
        box-shadow: var(--card-shadow);
        padding: 1.8rem 2.2rem; /* Increased padding */
        margin-bottom: 2rem;
        transition:
          background-color 0.2s ease,
          border-color 0.2s ease,
          box-shadow 0.3s ease;
      }

      /* Report Cover/Header Card */
      #report-header-card {
        text-align: center;
      }
      #report-header-card #report-title {
        font-size: 2.4rem; /* Prominent title */
        font-weight: 700;
        color: var(--primary-color);
        margin-top: 0;
        margin-bottom: 0.75rem;
      }
      #report-header-card #report-description {
        font-size: 1.1rem;
        color: var(--text-muted-color);
        margin-bottom: 1.5rem;
        max-width: 750px;
        margin-left: auto;
        margin-right: auto;
      }
      #report-header-card .cover-info {
        font-size: 0.9rem;
        color: var(--text-muted-color);
      }
      #report-header-card .cover-info p {
        margin-bottom: 0.3rem;
      }

      /* Dimension Sections Card */
      .dimension-section {
        opacity: 0;
        transform: translateY(20px);
        transition:
          opacity 0.6s ease,
          transform 0.6s ease;
      }

      .dimension-section.active {
        opacity: 1;
        transform: translateY(0);
      }

      /* 确保初始可见性 */
      body.content-loaded .dimension-section {
        opacity: 1;
        transform: translateY(0);
      }
      .dimension-section .analysis-goal {
        /*一级标题*/
        font-size: 1.8rem;
        color: var(--text-color);
        border-bottom: 2px solid var(--primary-color);
        padding-bottom: 0.6rem;
        margin-top: 0;
        margin-bottom: 1.2rem; /* Spacing after L1 heading */
      }
      .dimension-section .dimension-name {
        /*二级标题*/
        font-size: 1.45rem;
        color: var(--primary-color);
        margin-top: 1.5rem;
        margin-bottom: 0.5rem;
      }
      .dimension-section .dimension-description {
        font-style: italic;
        color: var(--text-muted-color);
        margin-bottom: 1.5rem;
        font-size: 0.95rem;
        padding-left: 1rem; /* Indent description slightly */
        border-left: 3px solid var(--border-color);
      }

      /* Analysis Result (Markdown) Styling */
      .analysis-result {
        line-height: 1.75;
        font-size: 0.95rem; /* Base font for markdown content */
      }
      .analysis-result h1,
      .analysis-result h2,
      .analysis-result h3,
      .analysis-result h4 {
        margin-top: 1.8em;
        margin-bottom: 0.8em;
        font-weight: 600;
        padding-bottom: 0.3em;
        border-bottom: 1px solid var(--border-color);
      }
      .analysis-result h1 {
        font-size: 1.6em;
      }
      .analysis-result h2 {
        font-size: 1.4em;
      }
      .analysis-result h3 {
        font-size: 1.2em;
      }
      .analysis-result p {
        margin-bottom: 1em;
      }
      .analysis-result ul,
      .analysis-result ol {
        margin-left: 1.5rem;
        margin-bottom: 1em;
      }
      .analysis-result li {
        margin-bottom: 0.4em;
      }
      .analysis-result table {
        width: 100%;
        border-collapse: collapse;
        margin: 1.8rem 0;
        font-size: 0.9rem;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
        border-radius: 8px;
        overflow: hidden; /* For border-radius to apply to th/td */
      }
      .analysis-result th,
      .analysis-result td {
        padding: 0.8rem 1rem;
        text-align: left;
      }
      .analysis-result th {
        background-color: rgba(var(--primary-color-rgb), 0.07); /* Lighter heading for table */
        font-weight: 500;
        color: var(--text-color);
      }
      .analysis-result tr:nth-child(even) td {
        background-color: rgba(var(--primary-color-rgb), 0.02);
      }
      :root.dark-theme .analysis-result tr:nth-child(even) td {
        background-color: rgba(var(--primary-color-rgb), 0.04);
      }
      .analysis-result blockquote {
        border-left: 4px solid var(--primary-color);
        padding: 0.8rem 1.2rem;
        margin: 1.5rem 0;
        background-color: rgba(var(--primary-color-rgb), 0.04);
        border-radius: 0 6px 6px 0;
        color: var(--text-muted-color);
      }
      .analysis-result pre {
        background-color: var(--bg-alt-color);
        border: 1px solid var(--border-color);
        padding: 1rem;
        border-radius: 6px;
        overflow-x: auto;
        font-size: 0.875em; /* Slightly larger code font */
        line-height: 1.6;
        margin: 1.5rem 0;
      }
      .analysis-result code {
        font-family: monospace;
        background-color: rgba(var(--primary-color-rgb), 0.05);
        padding: 0.2em 0.4em;
        border-radius: 3px;
        font-size: 0.9em;
      }
      :root.dark-theme .analysis-result pre {
        background-color: #22272e; /* GitHub dark code block */
        border-color: #30363d;
      }
      :root.dark-theme .analysis-result code {
        background-color: rgba(var(--primary-color-rgb), 0.15);
      }

      /* Chart Container Styling */
      .chart-container {
        margin: 2rem 0 1rem 0; /* Adjusted margin */
        padding: 1.5rem; /* More padding */
        border-radius: var(--card-border-radius);
        background-color: var(--bg-alt-color);
        height: 420px; /* Default height */
        box-shadow: 0 2px 6px rgba(0, 0, 0, 0.03);
        transition:
          background-color 0.2s ease,
          border-color 0.2s ease;
      }

      /* Loading Indicator Styling */
      .loading-indicator {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        padding: 3rem 1rem; /* More padding */
        text-align: center;
        color: var(--text-muted-color);
      }
      .spinner {
        width: 36px; /* Slightly smaller spinner */
        height: 36px;
        border-left-color: var(--primary-color);
        border-radius: 50%;
        animation: spin 0.8s linear infinite; /* Faster spin */
        margin-bottom: 1rem;
      }
      @keyframes spin {
        to {
          transform: rotate(360deg);
        }
      }
      .loading-indicator p {
        font-size: 1rem;
      }

      /* Error Message Card Styling */
      .error-message-card {
        text-align: center;
        padding: 2rem 1.5rem;
      }
      .error-message-card h2 {
        color: var(--danger-color);
        margin-top: 0;
        font-size: 1.5rem;
      }
      .error-message-card p {
        color: var(--danger-color);
        font-size: 1.05rem;
      }

      /* Floating TOC Styling */
      .floating-toc-container h3 {
        font-size: 1.05rem; /* Slightly larger TOC title */
        font-weight: 600;
        margin-top: 0;
        margin-bottom: 1rem;
        padding-bottom: 0.6rem;
        border-bottom: 1px solid var(--border-color);
        color: var(--primary-color);
      }
      .floating-toc-list {
        list-style: none;
        padding: 0;
        margin: 0;
      }
      .floating-toc-list li a {
        display: block;
        padding: 0.45rem 0.8rem;
        font-size: 0.875rem;
        color: var(--text-muted-color);
        border-radius: 6px;
        transition: all 0.15s ease;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        border-left: 3px solid transparent; /* Marker for active state */
      }
      .floating-toc-list li a:hover {
        background-color: var(--toc-active-bg);
        color: var(--primary-color);
        text-decoration: none;
        transform: translateX(3px); /* Slight indent on hover */
      }
      .floating-toc-list li.active > a {
        /* Target direct child a */
        color: var(--primary-color);
        font-weight: 500;
        background-color: var(--toc-active-bg);
        border-left-color: var(--toc-active-border);
      }

      /* Analysis Goal Heading Card */
      .analysis-goal-heading {
        padding: 1rem 2.2rem; /* Slightly less padding than dimension cards */
        margin-bottom: 1rem; /* Space before the first dimension card */
        font-size: 1.9rem; /* More prominent */
        font-weight: 700;
        color: var(--primary-color);
        border-left: 5px solid var(--primary-color);
        border-radius: var(--card-border-radius);
        background-color: rgba(var(--primary-color-rgb), 0.05);
        border: none; /* Remove default card border */
        box-shadow: none; /* Remove default card shadow */
        transition: background-color 0.2s ease;
      }
      :root.dark-theme .analysis-goal-heading {
        background-color: rgba(var(--primary-color-rgb), 0.1);
      }

      /* Floating TOC Hierarchy Styling */
      .floating-toc-list .toc-level-1 > a {
        font-weight: 600; /* Bolder Level 1 */
        color: var(--text-color);
        padding: 0.5rem 0.8rem; /* Adjust padding */
      }
      .floating-toc-list .toc-level-1.active-parent > a {
        color: var(--primary-color); /* Highlight active parent */
      }
      .floating-toc-list .toc-nested-list {
        list-style: none;
        padding-left: 1.2rem; /* Indentation for Level 2 */
        margin-top: 0.2rem;
        margin-bottom: 0.5rem;
      }
      .floating-toc-list .toc-level-2 a {
        /* Styles inherited, maybe slightly smaller/muted */
        font-size: 0.85rem;
      }
      .floating-toc-list .toc-level-2.active a {
        /* Active state already handled by .active > a in previous CSS */
      }
      .toc-item-muted {
        padding: 0.45rem 0.8rem;
        color: var(--text-muted-color);
        font-style: italic;
        font-size: 0.85rem;
      }

      /* Print styles */
      @media print {
        body {
          background-color: #fff !important;
          color: #000 !important;
          font-size: 10pt;
          line-height: 1.4;
          opacity: 1 !important;
        }
        nav,
        footer,
        .floating-toc-container,
        .floating-toc-toggle-btn,
        .theme-toggle-btn-nav {
          display: none !important;
        }
        .page-wrapper {
          max-width: 100% !important;
          padding: 0 !important;
          margin: 0 !important;
        }
        .main-content {
          padding-right: 0 !important;
        }
        .report-section-card,
        .chart-container {
          box-shadow: none !important;
          padding: 0.8rem;
          margin-bottom: 1rem;
          page-break-inside: avoid;
          border-radius: 0 !important;
        }
        h1,
        h2,
        h3,
        h4,
        h5,
        h6 {
          color: #000 !important;
          margin-top: 1.2em;
          margin-bottom: 0.5em;
          border: none !important;
          padding-bottom: 0 !important;
        }
        h1 {
          font-size: 18pt;
        }
        h2 {
          font-size: 15pt;
        }
        h3 {
          font-size: 13pt;
        }
        a {
          color: #000 !important;
          text-decoration: none !important;
        }
        .dimension-section .analysis-goal,
        .dimension-section .dimension-name {
          border-bottom: 1px solid #666 !important;
        }
        :root,
        :root.dark-theme {
          /* Override all theme colors for print */
          --bg-color: #ffffff !important;
          --text-color: #000000 !important;
          --text-muted-color: #333333 !important;
          --primary-color: #000000 !important;
          --border-color: #cccccc !important;
          --card-bg-color: #ffffff !important;
          --toc-bg-color: #ffffff !important;
          --toc-active-border: #000000 !important;
          --danger-color: #000000 !important;
        }
        .analysis-result table,
        .analysis-result th,
        .analysis-result td {
          font-size: 9pt;
        }
        .analysis-result th {
          background-color: #eee !important;
        }
        .chart-container {
          height: 300px !important;
        }
      }

      /* Data Visualization Background Animation */
      .data-bg-animation {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: -1;
        overflow: hidden;
        opacity: 0.7;
        transition: opacity 0.3s ease-in-out;
      }

      .data-bg-animation canvas {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
      }

      @media print {
        .data-bg-animation {
          display: none !important;
        }
      }

      /* Word风格页面视图模式 */
      .page-view-toggle-container {
        position: fixed;
        bottom: 20px;
        right: 20px;
        z-index: 1000;
      }

      /* 页面视图样式 */
      body.page-view-mode {
        background-color: #f0f0f0;
      }

      body.page-view-mode .data-bg-animation {
        opacity: 0.2;
      }

      body.page-view-mode .page-wrapper {
        max-width: none;
        padding: 30px;
      }

      body.page-view-mode .main-content {
        padding-right: 0;
        width: 100%;
        max-width: 100%;
      }

      /* Word页面容器 */
      body.page-view-mode .report-page {
        width: var(--page-width);
        min-height: var(--page-height);
        margin: 30px auto;
        padding: var(--page-margin);
        background-color: var(--page-bg-color);
        box-shadow: none; /* 移除阴影 */
        position: relative;
        page-break-after: always;
        border: none; /* 移除边框 */
      }

      body.page-view-mode .report-page:not(:last-child) {
        margin-bottom: 30px;
      }

      /* 页面顶部水印和页码 */
      body.page-view-mode .page-number {
        position: absolute;
        bottom: 10mm;
        right: 10mm;
        font-size: 10pt;
        color: var(--text-muted-color);
      }

      body.page-view-mode .page-watermark {
        position: absolute;
        top: 10mm;
        right: 10mm;
        font-size: 9pt;
        color: var(--text-muted-color);
      }

      /* 页面视图下的首页样式 */
      body.page-view-mode .report-page.cover-page {
        text-align: center;
        display: flex;
        flex-direction: column;
        justify-content: center;
      }

      body.page-view-mode .report-page.cover-page h1 {
        margin-top: 0;
        padding-top: 0;
      }

      /* 页面视图下隐藏卡片样式 */
      body.page-view-mode .report-section-card {
        box-shadow: none;
        border: none;
        border-radius: 0;
        padding: 0;
        margin: 0 0 1.5rem 0;
        background-color: transparent;
      }

      body.page-view-mode .analysis-goal-heading {
        padding: 0;
        margin: 1rem 0;
        border-left: none;
        border-radius: 0;
        box-shadow: none;
        background-color: transparent;
      }

      /* 页面视图下目录保持原样 */
      body.page-view-mode .floating-toc-container {
        position: fixed;
      }

      /* 页面布局相关样式 */
      @media print {
        /* 打印时隐藏非页面内容 */
        nav,
        .floating-toc-container,
        .floating-toc-toggle-btn,
        .data-bg-animation {
          display: none !important;
        }

        body {
          background: none !important;
          margin: 0 !important;
          padding: 0 !important;
        }

        .page-wrapper {
          margin: 0 !important;
          padding: 0 !important;
          max-width: none !important;
        }

        .main-content {
          margin: 0 !important;
          padding: 0 !important;
          width: 100% !important;
        }

        body.page-view-mode .report-page {
          box-shadow: none !important;
          margin: 0 !important;
          border: none !important;
          page-break-after: always;
          min-height: auto;
          /* 调整页边距，避免浏览器自动添加的边距 */
          padding: var(--page-margin);
        }

        /* 确保打印时没有背景色 */
        body.page-view-mode .report-page {
          -webkit-print-color-adjust: exact !important;
          color-adjust: exact !important;
          print-color-adjust: exact !important;
        }
      }

      /* 页面视图切换按钮移到顶部后的样式 */
      .page-view-toggle {
        display: flex;
        align-items: center;
        opacity: 0.9;
        transition: opacity 0.2s ease;
      }

      .page-view-toggle:hover {
        opacity: 1;
      }

      /* 删除固定位置的样式 */
      .page-view-toggle-container {
        position: fixed;
        bottom: 20px;
        right: 20px;
        z-index: 1000;
      }

      /* 分析结果在页面视图下的样式 */
      body.page-view-mode .analysis-result {
        font-size: 11pt;
        line-height: 1.5;
      }

      body.page-view-mode .chart-container {
        border: none;
        padding: 0;
        margin: 1rem 0;
        height: 300px; /* 较小的图表高度 */
      }

      /* Button tooltip styles */
      .btn-icon {
        padding: 0.5rem;
        font-size: 1.2rem;
        position: relative;
        margin-left: 0.75rem;
      }

      .btn-icon svg {
        width: 1.3em;
        height: 1.3em;
      }

      /* 确保导航栏按钮有合适的间距 */
      nav .actions {
        display: flex;
        align-items: center;
      }

      nav .actions .btn:first-child {
        margin-left: 0;
      }

      /* 响应式调整 */
      @media (max-width: 600px) {
        .btn-icon {
          padding: 0.4rem;
        }

        nav .actions .btn {
          margin-left: 0.4rem;
        }
      }

      /* 打印模式下的特殊样式 */
      body.print-mode {
        background: white !important;
      }

      /* 页面布局相关样式 */
      @media print {
        /* 打印时隐藏非页面内容 */
        nav,
        .floating-toc-container,
        .floating-toc-toggle-btn,
        .data-bg-animation {
          display: none !important;
        }

        body {
          background: white !important;
          margin: 0 !important;
          padding: 0 !important;
        }

        .page-wrapper {
          margin: 0 !important;
          padding: 0 !important;
          max-width: none !important;
          width: 100% !important;
        }

        .main-content {
          margin: 0 !important;
          padding: 0 !important;
          width: 100% !important;
        }

        body.page-view-mode .report-page {
          box-shadow: none !important;
          margin: 0 !important;
          border: none !important;
          page-break-after: always;
          min-height: auto;
          /* 调整页边距，避免浏览器自动添加的边距 */
          padding: 10mm !important; /* 减小打印边距 */
          width: auto !important;
          max-width: 100% !important;
        }

        /* 确保打印时没有背景色 */
        body.page-view-mode .report-page {
          -webkit-print-color-adjust: exact !important;
          color-adjust: exact !important;
          print-color-adjust: exact !important;
          background-color: white !important;
        }

        /* 打印时其他需要处理的元素 */
        .chart-container {
          page-break-inside: avoid;
        }

        /* 避免标题跨页 */
        h1,
        h2,
        h3,
        .dimension-name,
        .analysis-goal-heading {
          page-break-after: avoid;
          page-break-inside: avoid;
        }

        /* 表格处理 */
        table {
          page-break-inside: avoid;
        }
      }
    </style>
  </head>

  <body>
    <!-- 添加数据可视化背景动画 -->
    <div class="data-bg-animation" id="data-bg-animation"></div>

    <nav id="main-nav">
      <div class="logo-area">DataTK数据分析平台</div>
      <div class="actions">
        <button
          style="display: none"
          class="btn btn-outline btn-icon page-view-toggle"
          id="toggle-page-view"
          title="切换页面视图"
        >
          <svg viewBox="0 0 24 24">
            <path
              fill="currentColor"
              d="M3 6h18v2H3V6m0 4h18v2H3v-2m0 4h18v2H3v-2m0 4h18v2H3v-2z"
            ></path>
          </svg>
        </button>
        <button
          class="btn btn-outline btn-icon theme-toggle-btn-nav"
          id="theme-toggle-btn-nav"
          title="切换主题"
        >
          <svg class="icon-light" viewBox="0 0 24 24">
            <path
              fill="currentColor"
              d="M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zM12 1V3m0 18v2M4.22 4.22l1.42 1.42m12.72 12.72l1.42 1.42M1 12h2m18 0h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42z"
            ></path>
          </svg>
          <svg class="icon-dark" viewBox="0 0 24 24" style="display: none">
            <path
              fill="currentColor"
              d="M10 2c-1.82 0-3.53.5-5 1.35 2.99 1.73 5 4.95 5 8.65s-2.01 6.92-5 8.65C6.47 21.5 8.18 22 10 22c5.52 0 10-4.48 10-10S15.52 2 10 2z"
            ></path>
          </svg>
        </button>
        <button class="btn btn-outline btn-icon" onclick="window.print()" title="打印">
          <svg viewBox="0 0 24 24">
            <path
              fill="currentColor"
              d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"
            ></path>
          </svg>
        </button>
        <button
          class="btn btn-primary btn-icon"
          onclick="exportToPdf()"
          title="导出PDF"
          style="display: none"
        >
          <svg viewBox="0 0 24 24">
            <path
              fill="currentColor"
              d="M19 9h-4V3H9v6H5l7 7 7-7zm-8 2V5.5l1.5 1.5L11 8.5V11H9.5V9H8v2h3zm10-5H5c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V8l-4-4zM7 17v-2h10v2H7zm10-4H7v-2h10v2zm0-4H7V7h10v2z"
            ></path>
          </svg>
        </button>
      </div>
    </nav>

    <button class="floating-toc-toggle-btn btn btn-outline" id="floating-toc-toggle-btn">
      <svg viewBox="0 0 24 24">
        <path fill="currentColor" d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path>
      </svg>
      <span class="sr-only">目录</span>
    </button>

    <div class="page-wrapper">
      <main class="main-content">
        <section id="report-header-card">
          <h1 id="report-title">报告加载中...</h1>
          <p id="report-description"></p>
          <div class="cover-info">
            <p>创建时间: <span id="created-at"></span></p>
            <p style="display: none">报告ID: <span id="report-id"></span></p>
          </div>
          <div id="loading-indicator" class="loading-indicator"></div>
        </section>

        <div id="report-content-sections"></div>
      </main>

      <aside class="floating-toc-container hidden-desktop" id="floating-toc-container">
        <button class="close-toc-btn" id="close-toc-btn">&times;</button>
        <h3>目录导航</h3>
        <ul class="floating-toc-list" id="floating-toc-list">
          <!-- 动态生成目录将填充这里 -->
        </ul>
      </aside>
    </div>

    <!-- Theme toggle button removed from fixed position -->

    <!-- Footer element and its content have been removed -->

    <script>
      // --- Utility Functions ---
      function getUrlParam(name) {
        const urlParams = new URLSearchParams(window.location.search)
        return urlParams.get(name)
      }

      // --- Initialization and Event Listeners ---
      let navHeight = 60 // Default, will be updated

      document.addEventListener('DOMContentLoaded', () => {
        const navElement = document.getElementById('main-nav')
        if (navElement) {
          navHeight = navElement.offsetHeight
          document.documentElement.style.setProperty('--nav-height', navHeight + 'px')
        }

        // 立即添加content-loaded类，确保内容可见
        document.body.classList.add('content-loaded')

        initTheme()
        setupThemeToggle()
        setupFloatingTocInteraction()
        initDataVisualizationBg() // 初始化数据可视化背景

        // 异步加载报告数据
        setTimeout(() => {
          fetchReportData() // Load the actual report data
        }, 100)
      })

      function initTheme() {
        const savedTheme = localStorage.getItem('theme')
        const prefersDark =
          window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
        const lightIcon = document.querySelector('.theme-toggle-btn-nav .icon-light')
        const darkIcon = document.querySelector('.theme-toggle-btn-nav .icon-dark')

        if (savedTheme === 'dark' || (!savedTheme && prefersDark)) {
          document.documentElement.classList.add('dark-theme')
          if (lightIcon) lightIcon.style.display = 'none'
          if (darkIcon) darkIcon.style.display = 'inline-block'
        } else {
          document.documentElement.classList.remove('dark-theme')
          if (lightIcon) lightIcon.style.display = 'inline-block'
          if (darkIcon) darkIcon.style.display = 'none'
        }
      }

      function setupThemeToggle() {
        const toggleBtnNav = document.getElementById('theme-toggle-btn-nav')
        if (!toggleBtnNav) return

        const lightIcon = toggleBtnNav.querySelector('.icon-light')
        const darkIcon = toggleBtnNav.querySelector('.icon-dark')

        toggleBtnNav.addEventListener('click', () => {
          const isDark = document.documentElement.classList.toggle('dark-theme')
          localStorage.setItem('theme', isDark ? 'dark' : 'light')
          if (isDark) {
            if (lightIcon) lightIcon.style.display = 'none'
            if (darkIcon) darkIcon.style.display = 'inline-block'
          } else {
            if (lightIcon) lightIcon.style.display = 'inline-block'
            if (darkIcon) darkIcon.style.display = 'none'
          }
        })
      }

      function setupFloatingTocInteraction() {
        const tocContainer = document.getElementById('floating-toc-container')
        const tocToggleBtn = document.getElementById('floating-toc-toggle-btn')
        const closeTocBtn = document.getElementById('close-toc-btn')

        if (!tocContainer || !tocToggleBtn || !closeTocBtn) {
          console.warn('TOC elements not found for interaction setup.')
          return
        }

        const openToc = () => {
          tocContainer.classList.add('show')
          tocToggleBtn.classList.add('hidden')
        }
        const closeToc = () => {
          tocContainer.classList.remove('show')
          if (window.innerWidth < 1024) {
            // Only show toggle on small screens
            tocToggleBtn.classList.remove('hidden')
          }
        }

        tocToggleBtn.addEventListener('click', openToc)
        closeTocBtn.addEventListener('click', closeToc)

        // Close TOC when clicking outside on mobile/tablet
        document.addEventListener('click', function (event) {
          if (window.innerWidth < 1024 && tocContainer.classList.contains('show')) {
            const isClickInsideToc = tocContainer.contains(event.target)
            const isClickOnToggleBtn = tocToggleBtn.contains(event.target)
            if (!isClickInsideToc && !isClickOnToggleBtn) {
              closeToc()
            }
          }
        })

        // Adjust on resize
        window.addEventListener('resize', () => {
          if (window.innerWidth >= 1024) {
            // Desktop
            tocContainer.classList.remove('show') // Not using 'show' for desktop
            tocContainer.classList.remove('hidden-desktop') // Make sure it's visible
            tocToggleBtn.classList.add('hidden')
            closeTocBtn.classList.add('hidden')
          } else {
            // Tablet/Mobile
            tocContainer.classList.add('hidden-desktop') // Hide if not explicitly shown
            if (!tocContainer.classList.contains('show')) {
              // if it's not already open
              tocToggleBtn.classList.remove('hidden')
            }
            closeTocBtn.classList.remove('hidden') // Close button always available when TOC is for mobile
          }
        })
        // Initial setup based on screen size
        if (window.innerWidth >= 1024) {
          tocContainer.classList.remove('hidden-desktop')
          tocToggleBtn.classList.add('hidden')
          closeTocBtn.classList.add('hidden')
        } else {
          tocContainer.classList.add('hidden-desktop')
          tocToggleBtn.classList.remove('hidden')
          closeTocBtn.classList.remove('hidden')
        }
      }

      // --- Data Fetching and Rendering Logic ---
      async function fetchReportData() {
        console.log('开始获取报告数据...')
        // 不移除content-loaded类，保持内容可见
        // document.body.classList.remove('content-loaded')

        // 更灵活地查找元素 - 使用选择器而不仅是getElementById
        const loadingIndicator = document.querySelector('#loading-indicator')
        const reportHeaderCard = document.querySelector('#report-header-card')

        if (loadingIndicator) loadingIndicator.classList.remove('hidden')
        if (reportHeaderCard) reportHeaderCard.classList.remove('report-section-card') // Hide header card styling during load

        const reportId = getUrlParam('report_id')
        if (!reportId) {
          showError('未提供报告ID参数')
          return
        }

        try {
          const formData = new FormData()
          formData.append('report_id', reportId)
          const token = localStorage.getItem('token')

          if (!token) {
            showError('您尚未登录或登录已过期，请返回系统重新登录')
            return
          }

          const response = await fetch('/dk/sessions/get_report_details', {
            method: 'POST',
            body: formData,
            headers: { Authorization: `Bearer ${token}` },
          })

          console.log('API Response Status:', response.status)

          if (response.status === 401) {
            showError('认证失败，您可能需要重新登录')
            return
          }
          if (!response.ok) {
            let errorBody = ''
            try {
              errorBody = await response.text()
            } catch (e) {}
            throw new Error(`API请求失败: ${response.status} ${response.statusText}. ${errorBody}`)
          }

          const data = await response.json()
          console.log('API Response Data:', data)

          if (data.status !== 'success') {
            throw new Error(data.message || 'API返回错误状态')
          }
          renderReport(data)
        } catch (error) {
          console.error('获取报告数据失败:', error)
          showError(`获取报告数据失败: ${error.message}`)
        } finally {
          if (loadingIndicator) loadingIndicator.classList.add('hidden')
          if (reportHeaderCard) reportHeaderCard.classList.add('report-section-card') // Re-apply card style

          // 确保页面已加载完成
          document.body.classList.add('content-loaded')

          // Call setupScrollSpy *after* content is rendered and visible
          requestAnimationFrame(() => {
            // Ensure rendering is complete
            setupScrollSpy()
            setupScrollAnimations() // Also trigger animations after render
          })
        }
      }

      function showError(message) {
        // 更灵活地查找元素 - 使用选择器而不仅是getElementById
        const reportTitleEl = document.querySelector('#report-title')
        const reportDescEl = document.querySelector('#report-description')
        const reportContentEl = document.querySelector('#report-content-sections')
        const loadingIndicator = document.querySelector('#loading-indicator')
        const reportHeaderCard = document.querySelector('#report-header-card')

        if (loadingIndicator) loadingIndicator.classList.add('hidden')
        if (reportHeaderCard) reportHeaderCard.classList.add('report-section-card') // Ensure header card style applies on error

        if (reportTitleEl) reportTitleEl.textContent = '加载失败'
        if (reportDescEl) reportDescEl.textContent = '' // Clear description on error

        if (reportContentEl) {
          // Clear previous content
          reportContentEl.innerHTML = ''
          // Add error message card
          const errorSection = document.createElement('section')
          errorSection.className = 'report-section-card error-message-card' // Use card style for error
          errorSection.innerHTML = `
                <h2><svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor" style="vertical-align: middle; margin-right: 0.3em;"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"></path></svg>错误提示</h2>
                <p>${message}</p>
            `
          reportContentEl.appendChild(errorSection)
        }
        console.error('错误:', message)
        document.body.classList.add('content-loaded') // Ensure body is visible to show error
      }

      function renderReport(data) {
        const report = data.report
        const dimensions = data.dimensions

        if (!report) {
          showError('报告数据无效，无法渲染。')
          return
        }

        document.getElementById('report-title').textContent = report.report_title || '无标题报告'
        document.getElementById('report-description').textContent = report.report_description || ''
        document.getElementById('created-at').textContent = formatDate(report.created_at)
        document.getElementById('report-id').textContent = report.id

        renderDimensions(dimensions)
        populateFloatingToc(dimensions)

        document.title = report.report_title || '数据分析报告'
        // content-loaded class is added in fetchReportData finally block
      }

      function formatDate(dateString) {
        if (!dateString) return '未知'
        try {
          // Attempt more robust parsing and formatting
          const date = new Date(dateString)
          if (isNaN(date.getTime())) throw new Error('Invalid Date')
          return date.toLocaleString('zh-CN', {
            year: 'numeric',
            month: '2-digit',
            day: '2-digit',
            hour: '2-digit',
            minute: '2-digit',
            hour12: false,
          })
        } catch (e) {
          console.warn('日期格式化失败:', dateString, e)
          return dateString // Fallback to original string
        }
      }

      function renderDimensions(dimensions) {
        // 使用querySelector而不是getElementById
        const contentSectionsEl = document.querySelector('#report-content-sections')
        if (!contentSectionsEl) {
          console.error('未找到报告内容容器元素')
          return
        }

        contentSectionsEl.innerHTML = '' // Clear previous sections

        if (!dimensions || dimensions.length === 0) {
          contentSectionsEl.innerHTML =
            '<section class="report-section-card"><p style="text-align: center; color: var(--text-muted-color);">此报告没有分析维度内容</p></section>'
          return
        }

        const groupedDimensions = dimensions.reduce((acc, dimension, index) => {
          const goal = dimension.analysis_goal || '未分类分析'
          if (!acc[goal]) {
            acc[goal] = []
          }
          acc[goal].push({ ...dimension, originalIndex: index })
          return acc
        }, {})

        // Initialize top-level counter
        let groupCounter = 1
        Object.entries(groupedDimensions).forEach(([goal, goalDimensions]) => {
          const goalId = `goal-${groupCounter - 1}`
          const goalHeader = document.createElement('h2')
          goalHeader.className = 'analysis-goal-heading report-section-card'
          goalHeader.id = goalId
          // Add numbering to goal heading
          goalHeader.textContent = `${groupCounter}. ${goal}`
          contentSectionsEl.appendChild(goalHeader)

          // Initialize second-level counter for this group
          let dimensionIndexInGroup = 1
          goalDimensions.forEach((dimension) => {
            const sectionId = `dimension-${dimension.originalIndex}`
            const sectionEl = document.createElement('section')
            sectionEl.className = 'dimension-section report-section-card active' // 添加active类确保立即可见
            sectionEl.id = sectionId

            const safeMarkdown = dimension.analysis_result || ''
            const renderedHtml = renderMarkdown(safeMarkdown)

            // Add numbering to dimension name heading
            const dimensionNameText = `${groupCounter}.${dimensionIndexInGroup} ${dimension.dimension_name || '维度名称'}`

            sectionEl.innerHTML = `
                    <h3 class="dimension-name">${dimensionNameText}</h3>
                    ${dimension.dimension_description ? `<p class="dimension-description">${dimension.dimension_description}</p>` : ''}
                    <div class="analysis-result">${renderedHtml}</div>
                    ${dimension.json_data ? `<div class="chart-container"><canvas id="chart-${dimension.originalIndex}"></canvas></div>` : ''}
                `
            contentSectionsEl.appendChild(sectionEl)

            // 在渲染图表前确保已经添加到DOM中
            if (dimension.json_data) {
              // 使用requestAnimationFrame确保DOM已经完全更新
              requestAnimationFrame(() => {
                try {
                  const chartCanvas = document.querySelector(`#chart-${dimension.originalIndex}`)
                  if (chartCanvas) {
                    const chartData = JSON.parse(dimension.json_data)
                    renderChart(`chart-${dimension.originalIndex}`, chartData)
                  } else {
                    console.error(`未找到Canvas元素 chart-${dimension.originalIndex}`)
                  }
                } catch (error) {
                  console.error('解析或渲染图表失败:', error, dimension.json_data)
                  // 安全地查找图表容器
                  const chartContainer = sectionEl.querySelector('.chart-container')
                  if (chartContainer) {
                    chartContainer.innerHTML =
                      '<p style="color: var(--danger-color); text-align: center;">图表数据加载或渲染失败</p>'
                  }
                }
              })
            }
            // Increment second-level counter
            dimensionIndexInGroup++
          })
          // Increment top-level counter
          groupCounter++
        })

        // 在添加完内容后调用一次setupScrollAnimations
        requestAnimationFrame(() => {
          console.log('渲染完成，设置所有部分为可见状态')
          setupScrollAnimations()
        })
      }

      function renderMarkdown(markdownContent) {
        if (markdownContent === null || typeof markdownContent === 'undefined') return ''
        try {
          // Configure marked - disable deprecated options if using newer versions
          marked.setOptions({
            gfm: true,
            breaks: true, // Add <br> on single line breaks
            // Sanitize: false - BE VERY CAREFUL WITH THIS if content is user-generated
            // Consider using a sanitizer library like DOMPurify after marked:
            // marked.parse(content, (err, html) => { if (!err) return DOMPurify.sanitize(html); });
          })
          return marked.parse(markdownContent)
        } catch (error) {
          console.error('Markdown渲染失败:', error)
          const escapedContent = String(markdownContent).replace(/</g, '&lt;').replace(/>/g, '&gt;')
          return `<div class="report-section-card error-message-card" style="text-align: left;"> 
                      <p style="color:var(--danger-color)">Markdown 内容渲染出错。</p>
                      <pre style="white-space: pre-wrap; word-wrap: break-word;">${escapedContent}</pre>
                  </div>`
        }
      }

      function populateFloatingToc(dimensions) {
        const tocListEl = document.getElementById('floating-toc-list')
        const tocContainer = document.getElementById('floating-toc-container')
        if (!tocListEl || !tocContainer) return

        tocListEl.innerHTML = '' // Clear previous TOC items

        if (!dimensions || dimensions.length === 0) {
          tocListEl.innerHTML = '<li class="toc-item-muted">无分析内容</li>'
          return
        }

        const groupedDimensions = dimensions.reduce((acc, dimension, index) => {
          const goal = dimension.analysis_goal || '未分类分析'
          if (!acc[goal]) {
            acc[goal] = []
          }
          acc[goal].push({ ...dimension, originalIndex: index })
          return acc
        }, {})

        tocContainer.classList.remove('hidden')
        if (window.innerWidth < 1024 && !tocContainer.classList.contains('show')) {
          tocContainer.classList.add('hidden-desktop')
        } else if (window.innerWidth >= 1024) {
          tocContainer.classList.remove('hidden-desktop')
        }

        let tocHasContent = false
        let groupCounter = 1 // Initialize counter for TOC numbering
        Object.entries(groupedDimensions).forEach(([goal, goalDimensions]) => {
          const goalId = `goal-${groupCounter - 1}` // Keep original ID logic

          const goalLi = document.createElement('li')
          goalLi.classList.add('toc-level-1')
          const goalLink = document.createElement('a')
          goalLink.href = `#${goalId}`
          // Add numbering to Level 1 TOC item
          const goalText = `${groupCounter}. ${goal}`
          goalLink.textContent = goalText
          goalLink.title = goalText
          goalLink.addEventListener('click', (e) => {
            e.preventDefault()
            document.getElementById(goalId)?.scrollIntoView({ behavior: 'smooth', block: 'start' })
            if (window.innerWidth < 1024) closeToc()
          })
          goalLi.appendChild(goalLink)
          tocListEl.appendChild(goalLi)

          const nestedUl = document.createElement('ul')
          nestedUl.classList.add('toc-nested-list')

          let groupHasContent = false
          let dimensionIndexInGroup = 1 // Initialize counter for this group
          goalDimensions.forEach((dimension) => {
            const tocTextRaw = dimension.dimension_name
            if (tocTextRaw && tocTextRaw.trim() !== '') {
              groupHasContent = true
              tocHasContent = true
              const sectionId = `dimension-${dimension.originalIndex}`
              const dimensionLi = document.createElement('li')
              dimensionLi.classList.add('toc-level-2')
              const dimensionLink = document.createElement('a')
              dimensionLink.href = `#${sectionId}`
              // Add numbering to Level 2 TOC item
              const dimensionText = `${groupCounter}.${dimensionIndexInGroup} ${tocTextRaw}`
              dimensionLink.textContent = dimensionText
              dimensionLink.title = dimensionText
              dimensionLink.dataset.sectionId = sectionId
              dimensionLink.addEventListener('click', (e) => {
                e.preventDefault()
                document
                  .getElementById(sectionId)
                  ?.scrollIntoView({ behavior: 'smooth', block: 'start' })
                if (window.innerWidth < 1024) closeToc()
              })
              dimensionLi.appendChild(dimensionLink)
              nestedUl.appendChild(dimensionLi)
              // Increment second-level counter
              dimensionIndexInGroup++
            }
          })

          if (groupHasContent) {
            goalLi.appendChild(nestedUl)
          }
          // Increment top-level counter
          groupCounter++
        })

        if (!tocHasContent) {
          tocListEl.innerHTML = '<li class="toc-item-muted">无有效目录项</li>'
        }

        function closeToc() {
          const tocContainer = document.getElementById('floating-toc-container')
          const tocToggleBtn = document.getElementById('floating-toc-toggle-btn')
          if (tocContainer) tocContainer.classList.remove('show')
          if (tocToggleBtn && window.innerWidth < 1024) tocToggleBtn.classList.remove('hidden')
        }
      }

      let scrollSpyObserver = null // Store observer to disconnect later if needed

      function setupScrollSpy() {
        if (scrollSpyObserver) {
          scrollSpyObserver.disconnect()
        }

        const sections = Array.from(document.querySelectorAll('.dimension-section[id]'))
        const tocLinksLevel2 = Array.from(
          document.querySelectorAll('.floating-toc-list .toc-level-2 a[href^="#"]'),
        ) // Target level 2 links
        const tocList = document.getElementById('floating-toc-list')

        if (!sections.length || !tocLinksLevel2.length || !tocList) {
          console.log('ScrollSpy: Missing sections or L2 TOC links.')
          return
        }

        let lastActiveL2Link = null
        let lastActiveL1Li = null

        scrollSpyObserver = new IntersectionObserver(
          (entries) => {
            let bestVisibleSectionLink = null
            let maxVisibleRatio = 0

            entries.forEach((entry) => {
              const id = entry.target.getAttribute('id')
              // Find the corresponding LEVEL 2 link
              const correspondingLink = tocLinksLevel2.find((link) => link.dataset.sectionId === id)

              if (entry.isIntersecting && correspondingLink) {
                if (entry.intersectionRatio > maxVisibleRatio) {
                  maxVisibleRatio = entry.intersectionRatio
                  bestVisibleSectionLink = correspondingLink
                }
              }
            })

            if (bestVisibleSectionLink) {
              const activeL2Li = bestVisibleSectionLink.parentElement
              // Find the parent Level 1 LI
              const activeL1Li = activeL2Li?.closest('.toc-level-1')

              if (lastActiveL2Link !== bestVisibleSectionLink) {
                // Deactivate all level 2 links first
                tocLinksLevel2.forEach((link) => link.parentElement.classList.remove('active'))
                // Deactivate previous level 1 if different
                if (lastActiveL1Li && lastActiveL1Li !== activeL1Li) {
                  lastActiveL1Li.classList.remove('active-parent')
                }

                // Activate new level 2 and level 1
                activeL2Li.classList.add('active')
                if (activeL1Li) {
                  activeL1Li.classList.add('active-parent') // Add parent highlight class
                }

                lastActiveL2Link = bestVisibleSectionLink
                lastActiveL1Li = activeL1Li

                // Auto-scroll TOC list to keep active L2 item visible
                const tocRect = tocList.getBoundingClientRect()
                const activeLiRect = activeL2Li.getBoundingClientRect()

                if (activeLiRect.top < tocRect.top + 20) {
                  tocList.scrollTop -= tocRect.top - activeLiRect.top + 20
                } else if (activeLiRect.bottom > tocRect.bottom - 20) {
                  tocList.scrollTop += activeLiRect.bottom - tocRect.bottom + 20
                }
              }
            }
          },
          {
            rootMargin: '-15% 0px -55% 0px', // Adjusted trigger zone
            threshold: 0, // Trigger as soon as any part enters the zone
          },
        )

        sections.forEach((section) => scrollSpyObserver.observe(section))

        // Initial check remains similar, targeting L2 links
        const currentHash = window.location.hash
        if (currentHash) {
          const activeLink = tocLinksLevel2.find(
            (link) => link.getAttribute('href') === currentHash,
          )
          if (activeLink) {
            setTimeout(() => {
              const activeL2Li = activeLink.parentElement
              const activeL1Li = activeL2Li?.closest('.toc-level-1')
              tocLinksLevel2.forEach((link) => link.parentElement.classList.remove('active'))
              document
                .querySelectorAll('.toc-level-1.active-parent')
                .forEach((li) => li.classList.remove('active-parent'))
              activeL2Li.classList.add('active')
              if (activeL1Li) activeL1Li.classList.add('active-parent')
              lastActiveL2Link = activeLink
              lastActiveL1Li = activeL1Li
            }, 100)
          }
        }
      }

      function setupScrollAnimations() {
        // 首先让所有部分默认可见，以防止内容不可见问题
        const allSections = document.querySelectorAll('.dimension-section')
        allSections.forEach((section) => {
          section.classList.add('active')
        })

        console.log('已处理', allSections.length, '个维度部分，强制设置为可见')

        // 使用Intersection Observer只在支持的浏览器中使用
        if ('IntersectionObserver' in window) {
          const observer = new IntersectionObserver(
            (entries, obs) => {
              entries.forEach((entry) => {
                if (entry.isIntersecting) {
                  entry.target.classList.add('active')
                  obs.unobserve(entry.target) // Animate only once
                }
              })
            },
            { threshold: 0.1 }, // Trigger when 10% is visible
          )

          // 重新观察所有部分，主要用于滚动效果
          allSections.forEach((section) => observer.observe(section))
        }
      }

      function renderChart(canvasId, chartData) {
        const canvas = document.getElementById(canvasId)
        if (!canvas) {
          console.error(`Canvas元素 ${canvasId} 未找到`)
          return
        }
        const ctx = canvas.getContext('2d')
        if (!ctx) {
          console.error(`无法获取 ${canvasId} 的2D上下文`)
          return
        }

        // 基本数据验证
        if (!chartData || (typeof chartData !== 'object' && !Array.isArray(chartData))) {
          console.error(`${canvasId} 的图表数据无效:`, chartData)
          canvas.parentElement.innerHTML =
            '<p style="color: var(--danger-color); text-align: center;">无效的图表数据</p>'
          return
        }

        // 存储图表数据到canvas实例，便于页面视图切换时恢复
        canvas._chartData = chartData

        let chartType = 'bar' // 默认类型
        let labels = []
        let datasets = []
        let chartOptions = {}

        // 处理二维对象数组格式 [{key1: value1, key2: value2}, {key1: value3, key2: value4}]
        if (Array.isArray(chartData) && chartData.length > 0 && typeof chartData[0] === 'object') {
          const firstItem = chartData[0]
          const keys = Object.keys(firstItem)

          if (keys.length >= 2) {
            // 取第一个属性作为类别/标签，其余属性作为数据系列
            const categoryKey = keys[0]
            const valueKeys = keys.slice(1)

            // 提取类别/标签
            labels = chartData.map((item) => item[categoryKey])

            // 确定图表类型：饼图、柱状图或折线图
            if (valueKeys.length === 1 && labels.length <= 6) {
              // 单数据系列且类别少于6个，使用饼图
              chartType = 'pie'
              datasets = [
                {
                  data: chartData.map((item) => item[valueKeys[0]]),
                  backgroundColor: [
                    'rgba(88, 166, 255, 0.7)',
                    'rgba(129, 201, 149, 0.7)',
                    'rgba(253, 214, 99, 0.7)',
                    'rgba(248, 139, 130, 0.7)',
                    'rgba(114, 191, 205, 0.7)',
                    'rgba(173, 181, 189, 0.7)',
                  ],
                  borderColor: isDarkTheme() ? '#1c1c1c' : '#ffffff',
                  borderWidth: 2,
                },
              ]
            } else if (labels.length > 15) {
              // 数据点较多，使用折线图
              chartType = 'line'
              datasets = valueKeys.map((key, index) => {
                const colorIndex = index % 4
                const colors = [
                  { bg: 'rgba(88, 166, 255, 0.6)', border: 'rgba(88, 166, 255, 1)' },
                  { bg: 'rgba(129, 201, 149, 0.6)', border: 'rgba(129, 201, 149, 1)' },
                  { bg: 'rgba(253, 214, 99, 0.6)', border: 'rgba(253, 214, 99, 1)' },
                  { bg: 'rgba(248, 139, 130, 0.6)', border: 'rgba(248, 139, 130, 1)' },
                ]
                return {
                  label: key,
                  data: chartData.map((item) => item[key]),
                  backgroundColor: colors[colorIndex].bg,
                  borderColor: colors[colorIndex].border,
                  borderWidth: 1,
                  tension: 0.1,
                  fill: false,
                }
              })
            } else {
              // 默认使用柱状图
              chartType = 'bar'
              datasets = valueKeys.map((key, index) => {
                const colorIndex = index % 4
                const colors = [
                  { bg: 'rgba(88, 166, 255, 0.6)', border: 'rgba(88, 166, 255, 1)' },
                  { bg: 'rgba(129, 201, 149, 0.6)', border: 'rgba(129, 201, 149, 1)' },
                  { bg: 'rgba(253, 214, 99, 0.6)', border: 'rgba(253, 214, 99, 1)' },
                  { bg: 'rgba(248, 139, 130, 0.6)', border: 'rgba(248, 139, 130, 1)' },
                ]
                return {
                  label: key,
                  data: chartData.map((item) => item[key]),
                  backgroundColor: colors[colorIndex].bg,
                  borderColor: colors[colorIndex].border,
                  borderWidth: 1,
                }
              })
            }
          } else if (keys.length === 1) {
            // 只有一个键，数据不适合图表展示
            console.warn('数据只有一个属性，不适合图表展示:', chartData)
            canvas.parentElement.innerHTML =
              '<p style="color: var(--text-muted-color); text-align: center;">数据结构不适合图表展示</p>'
            return
          }
        } else if (chartData && typeof chartData === 'object') {
          // 处理旧格式的数据，保持兼容性
          if (Array.isArray(chartData.categories) && Array.isArray(chartData.values)) {
            // Common pattern for pie/bar
            labels = chartData.categories
            if (chartData.categories.length <= 6 && chartData.categories.length > 1) {
              // Few categories -> Pie
              chartType = 'pie'
              datasets = [
                {
                  data: chartData.values,
                  backgroundColor: [
                    'rgba(88, 166, 255, 0.7)',
                    'rgba(129, 201, 149, 0.7)',
                    'rgba(253, 214, 99, 0.7)',
                    'rgba(248, 139, 130, 0.7)',
                    'rgba(114, 191, 205, 0.7)',
                    'rgba(173, 181, 189, 0.7)',
                  ],
                  borderColor: isDarkTheme() ? '#1c1c1c' : '#ffffff',
                  borderWidth: 2,
                },
              ]
            } else {
              // More categories -> Bar
              chartType = 'bar'
              datasets = [
                {
                  label: chartData.seriesName || '数值',
                  data: chartData.values,
                  backgroundColor: 'rgba(var(--primary-color-rgb), 0.6)',
                  borderColor: 'rgba(var(--primary-color-rgb), 1)',
                  borderWidth: 1,
                },
              ]
            }
          } else if (Array.isArray(chartData.labels) && Array.isArray(chartData.values)) {
            // Alternative labels/values
            labels = chartData.labels
            datasets = [
              {
                label: chartData.seriesName || '数值',
                data: chartData.values,
                backgroundColor: 'rgba(var(--primary-color-rgb), 0.6)',
                borderColor: 'rgba(var(--primary-color-rgb), 1)',
                borderWidth: 1,
              },
            ]
            if (labels.length > 12) chartType = 'line' // Switch to line if many labels
          } else if (Array.isArray(chartData.series) && chartData.series.length > 0) {
            // Multi-series data
            // Assume first series dictates labels if not globally defined
            labels = chartData.labels || chartData.series[0].labels || []
            const defaultColors = [
              { bg: 'rgba(88, 166, 255, 0.6)', border: 'rgba(88, 166, 255, 1)' },
              { bg: 'rgba(129, 201, 149, 0.6)', border: 'rgba(129, 201, 149, 1)' },
              { bg: 'rgba(253, 214, 99, 0.6)', border: 'rgba(253, 214, 99, 1)' },
              { bg: 'rgba(248, 139, 130, 0.6)', border: 'rgba(248, 139, 130, 1)' },
            ]
            datasets = chartData.series.map((s, i) => ({
              label: s.name || `系列 ${i + 1}`,
              data: s.values,
              backgroundColor: defaultColors[i % defaultColors.length].bg,
              borderColor: defaultColors[i % defaultColors.length].border,
              borderWidth: 1,
              tension: 0.1, // Slight curve for line charts
              fill: false, // Default to no fill for line
            }))
            // If labels seem like time/dates or many points, default to line chart
            if (
              labels.length > 12 ||
              labels.some((l) => typeof l === 'string' && (l.includes('-') || l.includes('/')))
            ) {
              chartType = 'line'
              datasets.forEach((ds) => (ds.fill = false)) // No fill for line typically
            }
          } else {
            console.warn('无法识别的图表数据结构 for:', canvasId, chartData)
            canvas.parentElement.innerHTML =
              '<p style="color: var(--text-muted-color); text-align: center;">无法识别的图表数据结构</p>'
            return
          }
        } else {
          console.error('不支持的图表数据类型:', typeof chartData)
          canvas.parentElement.innerHTML =
            '<p style="color: var(--danger-color); text-align: center;">不支持的数据类型</p>'
          return
        }

        const themeIsDark = isDarkTheme()
        const gridColor = themeIsDark ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.07)'
        const ticksColor = themeIsDark ? '#9aa0a6' : '#6c757d'
        const legendColor = themeIsDark ? '#e8eaed' : '#212529'

        // 销毁已有图表实例
        let existingChart = Chart.getChart(canvas)
        if (existingChart) {
          existingChart.destroy()
        }

        try {
          new Chart(ctx, {
            type: chartType,
            data: { labels, datasets },
            options: {
              responsive: true,
              maintainAspectRatio: false,
              scales:
                chartType === 'pie'
                  ? {}
                  : {
                      y: {
                        beginAtZero: true,
                        grid: { color: gridColor, drawBorder: false },
                        ticks: { color: ticksColor, padding: 10 },
                      },
                      x: {
                        grid: { display: false, drawBorder: false },
                        ticks: { color: ticksColor, padding: 10 },
                      },
                    },
              plugins: {
                legend: {
                  display: chartType === 'pie' || datasets.length > 1,
                  position: 'bottom',
                  labels: { color: legendColor, padding: 20, usePointStyle: true, boxWidth: 8 },
                },
                tooltip: {
                  backgroundColor: themeIsDark
                    ? 'rgba(50, 50, 50, 0.9)'
                    : 'rgba(255, 255, 255, 0.95)',
                  titleColor: themeIsDark ? '#e8eaed' : '#212529',
                  bodyColor: themeIsDark ? '#e8eaed' : '#212529',
                  borderColor: themeIsDark ? '#30363d' : '#dee2e6',
                  borderWidth: 1,
                  padding: 10,
                  cornerRadius: 6,
                  usePointStyle: true,
                },
              },
              elements: {
                bar: { borderRadius: chartType === 'bar' ? 4 : 0 },
                line: { tension: 0.1 },
                point: { radius: 3, hoverRadius: 5 },
              },
              animation: {
                duration: 600,
                easing: 'easeOutQuad',
              },
            },
          })
        } catch (chartError) {
          console.error(`Chart.js渲染错误 for ${canvasId}:`, chartError)
          canvas.parentElement.innerHTML =
            '<p style="color: var(--danger-color); text-align: center;">图表渲染失败</p>'
        }
      }

      // 检查是否为暗色主题
      function isDarkTheme() {
        return document.documentElement.classList.contains('dark-theme')
      }

      function exportToPdf() {
        // 检查是否处于页面视图模式
        const isPageView = document.body.classList.contains('page-view-mode')
        // 记录原始状态
        const originalViewMode = isPageView

        if (!isPageView) {
          // 如果不是页面视图，询问用户是否切换
          if (
            confirm(
              '是否切换到页面视图模式后再导出PDF？页面视图模式下导出的PDF更接近Word文档的效果。',
            )
          ) {
            document.body.classList.add('page-view-mode')
            convertToPageView()
            // 给DOM时间更新
            setTimeout(() => {
              // 添加打印专用的class
              document.body.classList.add('print-mode')
              window.print()
              // 打印完成后恢复原始模式
              setTimeout(() => {
                document.body.classList.remove('print-mode')
                if (!originalViewMode) {
                  document.body.classList.remove('page-view-mode')
                  revertToNormalView()
                }
              }, 500)
            }, 500)
          } else {
            // 如果选择不切换，也添加打印模式class
            document.body.classList.add('print-mode')
            window.print()
            setTimeout(() => {
              document.body.classList.remove('print-mode')
            }, 500)
          }
        } else {
          // 如果已经是页面视图模式，添加打印专用class然后打印
          document.body.classList.add('print-mode')
          window.print()
          setTimeout(() => {
            document.body.classList.remove('print-mode')
          }, 500)
        }
      }

      // 数据可视化背景动画
      function initDataVisualizationBg() {
        const container = document.getElementById('data-bg-animation')
        if (!container) return

        // 创建Canvas元素
        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d')
        container.appendChild(canvas)

        // 设置Canvas尺寸
        function resizeCanvas() {
          canvas.width = window.innerWidth
          canvas.height = window.innerHeight
        }
        resizeCanvas()
        window.addEventListener('resize', resizeCanvas)

        // 粒子类
        class Particle {
          constructor(x, y, size, color, speed) {
            this.x = x
            this.y = y
            this.size = size
            this.color = color
            this.speedX = speed * (Math.random() - 0.5) * 2
            this.speedY = speed * (Math.random() - 0.5) * 2
            this.connections = [] // 存储连接的粒子
          }

          update() {
            // 更新位置
            this.x += this.speedX
            this.y += this.speedY

            // 边界检测（反弹）
            if (this.x < 0 || this.x > canvas.width) {
              this.speedX = -this.speedX
            }
            if (this.y < 0 || this.y > canvas.height) {
              this.speedY = -this.speedY
            }

            // 避免粒子超出画布
            this.x = Math.max(0, Math.min(canvas.width, this.x))
            this.y = Math.max(0, Math.min(canvas.height, this.y))
          }

          draw() {
            ctx.beginPath()
            ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2)
            ctx.fillStyle = this.color
            ctx.fill()
          }

          // 查找并存储距离小于指定值的粒子
          findConnections(particles, maxDistance) {
            this.connections = []
            particles.forEach((particle) => {
              if (particle !== this) {
                const dx = this.x - particle.x
                const dy = this.y - particle.y
                const distance = Math.sqrt(dx * dx + dy * dy)

                if (distance < maxDistance) {
                  this.connections.push({
                    particle: particle,
                    distance: distance,
                  })
                }
              }
            })
          }

          // 绘制连接线
          drawConnections() {
            this.connections.forEach((connection) => {
              const opacity = 1 - connection.distance / 150 // 距离越远线条越透明
              if (opacity > 0) {
                ctx.beginPath()
                ctx.moveTo(this.x, this.y)
                ctx.lineTo(connection.particle.x, connection.particle.y)

                // 从CSS变量获取线条颜色
                const lineColor = getComputedStyle(document.documentElement)
                  .getPropertyValue('--line-color')
                  .trim()

                ctx.strokeStyle = lineColor
                ctx.lineWidth = 0.5
                ctx.stroke()
              }
            })
          }
        }

        // 创建粒子数组
        const particles = []
        const particleCount = Math.min(
          50,
          Math.floor((window.innerWidth * window.innerHeight) / 15000),
        ) // 根据屏幕大小调整粒子数量

        // 获取CSS变量中定义的颜色
        function getParticleColor(index) {
          const colors = [
            getComputedStyle(document.documentElement)
              .getPropertyValue('--particle-color-1')
              .trim(),
            getComputedStyle(document.documentElement)
              .getPropertyValue('--particle-color-2')
              .trim(),
            getComputedStyle(document.documentElement)
              .getPropertyValue('--particle-color-3')
              .trim(),
            getComputedStyle(document.documentElement)
              .getPropertyValue('--particle-color-4')
              .trim(),
          ]
          return colors[index % colors.length]
        }

        // 初始化粒子
        for (let i = 0; i < particleCount; i++) {
          const size = Math.random() * 4 + 1
          const x = Math.random() * canvas.width
          const y = Math.random() * canvas.height
          const speed = 0.4
          const color = getParticleColor(i % 4)

          particles.push(new Particle(x, y, size, color, speed))
        }

        // 添加数据节点形状
        function addDataNodes() {
          // 添加几个特殊的大节点表示数据节点
          const nodeCount = Math.min(5, Math.floor(particleCount / 10))

          for (let i = 0; i < nodeCount; i++) {
            const size = Math.random() * 6 + 8 // 更大的节点
            const x = Math.random() * canvas.width
            const y = Math.random() * canvas.height
            const speed = 0.2 // 移动速度更慢
            const color = getParticleColor(0) // 使用主色调

            particles.push(new Particle(x, y, size, color, speed))
          }
        }

        addDataNodes()

        // 动画循环
        function animate() {
          // 清除画布
          ctx.clearRect(0, 0, canvas.width, canvas.height)

          // 更新所有粒子
          particles.forEach((particle) => {
            particle.update()
            particle.findConnections(particles, 150) // 查找距离小于150px的粒子
          })
          // 先绘制所有连接线
          particles.forEach((particle) => {
            particle.drawConnections()
          })

          // 再绘制所有粒子（这样粒子会显示在线上方）
          particles.forEach((particle) => {
            particle.draw()
          })

          // 继续动画循环
          requestAnimationFrame(animate)
        }

        // 开始动画
        animate()

        // 性能优化：当页面不可见时减少动画帧数
        document.addEventListener('visibilitychange', () => {
          if (document.hidden) {
            container.style.opacity = '0.3' // 降低不可见状态下的透明度
          } else {
            container.style.opacity = '0.7'
          }
        })
      }

      // --- 页面视图切换功能 ---
      document.addEventListener('DOMContentLoaded', () => {
        // 其他已有的DOMContentLoaded内容保持不变

        // 添加页面视图切换功能
        setupPageViewToggle()
      })

      function setupPageViewToggle() {
        const toggleButton = document.getElementById('toggle-page-view')
        if (!toggleButton) return

        // 默认清除localStorage中的设置，强制使用普通模式
        localStorage.removeItem('pageViewMode')

        // 初始状态下为非页面视图模式
        document.body.classList.remove('page-view-mode')

        toggleButton.addEventListener('click', () => {
          const isCurrentlyPagesView = document.body.classList.toggle('page-view-mode')
          localStorage.setItem('pageViewMode', isCurrentlyPagesView.toString())

          if (isCurrentlyPagesView) {
            toggleButton.title = '切换普通模式'
            convertToPageView()
          } else {
            toggleButton.title = '切换页面视图'
            revertToNormalView()
          }
        })
      }

      function convertToPageView() {
        // 如果已经转换过，不重复操作
        if (document.querySelector('.report-page')) return

        const mainContent = document.querySelector('.main-content')
        if (!mainContent) return

        const headerCard = document.getElementById('report-header-card')
        const contentSections = document.getElementById('report-content-sections')

        if (!headerCard || !contentSections) return

        // 创建一个临时容器存储原有内容
        const tempContainer = document.createElement('div')
        tempContainer.style.display = 'none'
        document.body.appendChild(tempContainer)

        // 保存原始内容
        tempContainer.appendChild(headerCard.cloneNode(true))
        Array.from(contentSections.children).forEach((child) => {
          tempContainer.appendChild(child.cloneNode(true))
        })

        // 清空主内容区
        mainContent.innerHTML = ''

        // 创建封面页
        const coverPage = document.createElement('div')
        coverPage.className = 'report-page cover-page'
        coverPage.innerHTML = `
          <h1>${document.getElementById('report-title').textContent || '数据分析报告'}</h1>
          <p>${document.getElementById('report-description').textContent || ''}</p>
          <div class="cover-info" style="margin-top: 50px;">
            <p>创建时间: ${document.getElementById('created-at').textContent || ''}</p>
            <p>报告ID: ${document.getElementById('report-id').textContent || ''}</p>
          </div>
          <div class="page-number">1</div>
        `

        mainContent.appendChild(coverPage)

        // 处理内容页 - 收集所有分析目标和维度
        const dimensions = collectDimensionsFromDOM()
        let pageNumber = 2 // 封面是第1页

        // 记录各大标题和维度的ID映射
        const sectionIdMap = {}

        // 按照分析目标分组处理
        Object.entries(dimensions).forEach(([goalName, goalDimensions], goalIndex) => {
          if (goalDimensions.length === 0) return

          // 创建新页面
          let currentPage = createNewPage(pageNumber++)
          mainContent.appendChild(currentPage)
          let currentPageHeight = 0

          // 存储分析目标ID映射
          const goalId = `goal-${goalIndex}`
          sectionIdMap[goalId] = `goal-page-${pageNumber - 1}`

          // 创建分析目标标题
          const goalHeader = document.createElement('h2')
          goalHeader.className = 'analysis-goal-heading'
          goalHeader.textContent = `${goalIndex + 1}. ${goalName}`
          goalHeader.id = `goal-page-${pageNumber - 1}` // 更新ID便于导航
          currentPage.appendChild(goalHeader)
          currentPageHeight += 20 // 降低标题高度估计，确保第一个维度可以跟标题在同一页

          // 处理该目标下的所有维度
          goalDimensions.forEach((dimension, dimIndex) => {
            const dimContent = document.createElement('section')
            dimContent.className = 'dimension-section report-section-card'

            // 保存原始维度ID和新页面模式下的ID映射
            const originalId = `dimension-${dimension.originalIndex}`
            const pageViewId = `dimension-page-${pageNumber - 1}-${dimIndex}`
            sectionIdMap[originalId] = pageViewId
            dimContent.id = pageViewId // 设置新ID

            // 估计当前维度内容的高度
            const contentEstimatedHeight = estimateDimensionHeight(dimension)

            // 检查是否需要新页面 - 仅当不是第一个维度且内容会超出页面时创建新页
            if (dimIndex > 0 && currentPageHeight + contentEstimatedHeight > 280) {
              // 280为A4页面内容高度
              // 创建新页面
              currentPage = createNewPage(pageNumber++)
              mainContent.appendChild(currentPage)
              currentPageHeight = 0

              // 更新页面ID
              const newPageViewId = `dimension-page-${pageNumber - 1}-${dimIndex}`
              sectionIdMap[originalId] = newPageViewId
              dimContent.id = newPageViewId
            }

            // 添加维度内容
            dimContent.innerHTML = `
              <h3 class="dimension-name">${goalIndex + 1}.${dimIndex + 1} ${dimension.name || '维度'}</h3>
              ${dimension.description ? `<p class="dimension-description">${dimension.description}</p>` : ''}
              <div class="analysis-result">${dimension.content || ''}</div>
              ${dimension.hasChart ? `<div class="chart-container"><canvas id="${dimension.chartId}"></canvas></div>` : ''}
            `

            currentPage.appendChild(dimContent)
            currentPageHeight += contentEstimatedHeight

            // 如果有图表，在下一个requestAnimationFrame中渲染
            if (dimension.hasChart && dimension.chartData) {
              requestAnimationFrame(() => {
                try {
                  const canvas = document.getElementById(dimension.chartId)
                  if (canvas) {
                    renderChart(dimension.chartId, dimension.chartData)
                  }
                } catch (e) {
                  console.error('重新渲染图表失败:', e)
                }
              })
            }
          })
        })

        // 存储ID映射关系以便目录点击导航
        window.sectionIdMap = sectionIdMap

        // 更新页面模式下目录的点击事件
        updateTocClickHandlers()
      }

      // 添加新函数用于更新目录点击事件
      function updateTocClickHandlers() {
        // 处理分析目标（一级目录）链接
        const goalLinks = document.querySelectorAll(
          '.floating-toc-list .toc-level-1 > a[href^="#"]',
        )
        goalLinks.forEach((link) => {
          const originalId = link.getAttribute('href').substring(1) // 移除#
          const newId = window.sectionIdMap && window.sectionIdMap[originalId]

          if (newId) {
            link.addEventListener('click', (e) => {
              e.preventDefault()
              document.getElementById(newId)?.scrollIntoView({ behavior: 'smooth', block: 'start' })
              if (window.innerWidth < 1024) closeToc()
            })
          }
        })

        // 处理维度（二级目录）链接
        const dimensionLinks = document.querySelectorAll(
          '.floating-toc-list .toc-level-2 a[href^="#"]',
        )
        dimensionLinks.forEach((link) => {
          const originalId = link.getAttribute('href').substring(1) // 移除#
          const newId = window.sectionIdMap && window.sectionIdMap[originalId]

          if (newId) {
            link.addEventListener('click', (e) => {
              e.preventDefault()
              document.getElementById(newId)?.scrollIntoView({ behavior: 'smooth', block: 'start' })
              if (window.innerWidth < 1024) closeToc()
            })
          }
        })

        // 重新设置ScrollSpy
        if (document.body.classList.contains('page-view-mode')) {
          setupPageViewScrollSpy()
        }
      }

      // 添加页面视图模式下的ScrollSpy
      function setupPageViewScrollSpy() {
        if (window.pageViewScrollSpyObserver) {
          window.pageViewScrollSpyObserver.disconnect()
        }

        // 获取页面视图模式下的所有维度部分
        const sections = Array.from(document.querySelectorAll('[id^="dimension-page-"]'))
        const tocLinksLevel2 = Array.from(
          document.querySelectorAll('.floating-toc-list .toc-level-2 a[href^="#"]'),
        )
        const tocList = document.getElementById('floating-toc-list')

        if (!sections.length || !tocLinksLevel2.length || !tocList) {
          return
        }

        let lastActiveL2Link = null
        let lastActiveL1Li = null

        window.pageViewScrollSpyObserver = new IntersectionObserver(
          (entries) => {
            let bestVisibleSectionId = null
            let maxVisibleRatio = 0

            entries.forEach((entry) => {
              if (entry.isIntersecting && entry.intersectionRatio > maxVisibleRatio) {
                maxVisibleRatio = entry.intersectionRatio
                bestVisibleSectionId = entry.target.getAttribute('id')
              }
            })

            if (bestVisibleSectionId) {
              // 查找对应于此新ID的原始ID
              let originalId = null
              for (const [origId, newId] of Object.entries(window.sectionIdMap || {})) {
                if (newId === bestVisibleSectionId && origId.startsWith('dimension-')) {
                  originalId = origId
                  break
                }
              }

              if (originalId) {
                // 找到对应的TOC链接
                const correspondingLink = tocLinksLevel2.find(
                  (link) => link.getAttribute('href') === `#${originalId}`,
                )

                if (correspondingLink && lastActiveL2Link !== correspondingLink) {
                  // 取消激活所有链接
                  tocLinksLevel2.forEach((link) => link.parentElement.classList.remove('active'))
                  document
                    .querySelectorAll('.toc-level-1.active-parent')
                    .forEach((li) => li.classList.remove('active-parent'))

                  // 激活新链接
                  const activeL2Li = correspondingLink.parentElement
                  const activeL1Li = activeL2Li?.closest('.toc-level-1')

                  activeL2Li.classList.add('active')
                  if (activeL1Li) {
                    activeL1Li.classList.add('active-parent')
                  }

                  lastActiveL2Link = correspondingLink
                  lastActiveL1Li = activeL1Li

                  // 自动滚动TOC
                  const tocRect = tocList.getBoundingClientRect()
                  const activeLiRect = activeL2Li.getBoundingClientRect()

                  if (activeLiRect.top < tocRect.top + 20) {
                    tocList.scrollTop -= tocRect.top - activeLiRect.top + 20
                  } else if (activeLiRect.bottom > tocRect.bottom - 20) {
                    tocList.scrollTop += activeLiRect.bottom - tocRect.bottom + 20
                  }
                }
              }
            }
          },
          {
            rootMargin: '-15% 0px -55% 0px',
            threshold: 0,
          },
        )

        sections.forEach((section) => window.pageViewScrollSpyObserver.observe(section))
      }

      // 修改revertToNormalView函数，确保返回普通模式时取消页面视图ScrollSpy
      function revertToNormalView() {
        // 获取原始内容的临时容器
        const tempContainer = document.querySelector('body > div[style="display: none;"]')
        if (!tempContainer) return

        // 清空当前主内容
        const mainContent = document.querySelector('.main-content')
        if (!mainContent) return

        mainContent.innerHTML = ''

        // 创建原始结构
        const headerCard = document.createElement('section')
        headerCard.id = 'report-header-card'
        headerCard.className = 'report-section-card'

        const contentSections = document.createElement('div')
        contentSections.id = 'report-content-sections'

        // 恢复原始内容
        // 首先恢复report-header-card
        const originalHeader = tempContainer.querySelector('[id="report-header-card"]')
        if (originalHeader) {
          headerCard.innerHTML = originalHeader.innerHTML
          mainContent.appendChild(headerCard)
        }

        // 然后恢复所有内容区块
        const originalSections = Array.from(
          tempContainer.querySelectorAll('.dimension-section, .analysis-goal-heading'),
        )
        originalSections.forEach((section) => {
          contentSections.appendChild(section.cloneNode(true))
        })

        mainContent.appendChild(contentSections)

        // 重新渲染所有图表
        requestAnimationFrame(() => {
          const chartContainers = Array.from(document.querySelectorAll('.chart-container canvas'))
          chartContainers.forEach((canvas) => {
            const chartId = canvas.id
            const originalCanvas = tempContainer.querySelector(`#${chartId}`)
            if (originalCanvas && originalCanvas._chart) {
              try {
                const chartData = originalCanvas._chartData
                if (chartData) {
                  renderChart(chartId, chartData)
                }
              } catch (e) {
                console.error('恢复图表失败:', e)
              }
            }
          })
        })

        // 取消页面视图ScrollSpy
        if (window.pageViewScrollSpyObserver) {
          window.pageViewScrollSpyObserver.disconnect()
          window.pageViewScrollSpyObserver = null
        }

        // 重置ID映射
        window.sectionIdMap = null

        // 重新设置原始ScrollSpy
        setupScrollSpy()

        // 移除临时容器
        // tempContainer.remove();
      }

      // 从DOM收集维度信息
      function collectDimensionsFromDOM() {
        const goals = {}

        // 获取所有分析目标
        const goalHeaders = document.querySelectorAll('.analysis-goal-heading')
        goalHeaders.forEach((goalHeader, goalIndex) => {
          const goalName = goalHeader.textContent.replace(/^\d+\.\s*/, '') // 移除编号
          goals[goalName] = []

          // 查找此目标后、下一个目标前的所有维度
          let currentElement = goalHeader.nextElementSibling
          let nextGoal = goalHeaders[goalIndex + 1]

          while (currentElement && (!nextGoal || !nextGoal.contains(currentElement))) {
            if (currentElement.classList.contains('dimension-section')) {
              const dimensionName =
                currentElement
                  .querySelector('.dimension-name')
                  ?.textContent.replace(/^\d+\.\d+\s*/, '') || ''
              const dimensionDesc =
                currentElement.querySelector('.dimension-description')?.textContent || ''
              const contentElement = currentElement.querySelector('.analysis-result')
              const chartContainer = currentElement.querySelector('.chart-container')
              const canvas = chartContainer?.querySelector('canvas')

              let chartData = null
              if (canvas && window.Chart) {
                const chart = Chart.getChart(canvas)
                if (chart) {
                  chartData = chart.data
                  // 保存到canvas实例以便恢复
                  canvas._chartData = chartData
                }
              }

              goals[goalName].push({
                name: dimensionName,
                description: dimensionDesc,
                content: contentElement?.innerHTML || '',
                hasChart: !!chartContainer,
                chartId: canvas?.id || '',
                chartData: chartData,
              })
            }

            currentElement = currentElement.nextElementSibling
            if (!currentElement && !nextGoal) break
          }
        })

        return goals
      }

      // 创建新的页面
      function createNewPage(pageNumber) {
        const page = document.createElement('div')
        page.className = 'report-page'

        // 添加页码
        const pageNumberDiv = document.createElement('div')
        pageNumberDiv.className = 'page-number'
        pageNumberDiv.textContent = pageNumber
        page.appendChild(pageNumberDiv)

        // 添加水印
        const watermark = document.createElement('div')
        watermark.className = 'page-watermark'
        watermark.textContent =
          document.getElementById('report-title')?.textContent || '数据分析报告'
        page.appendChild(watermark)

        return page
      }

      // 估计维度内容高度
      function estimateDimensionHeight(dimension) {
        // 基础高度
        let height = 40 // 降低维度标题基础高度

        // 描述文本
        if (dimension.description) {
          // 减少基础高度，更精确地基于字符数量估算
          const descLength = dimension.description.length
          height += 20 + (descLength / 150) * 15 // 更保守的估计：每150字符15mm
        }

        // 主要内容 - 使用字符数量估算，但更准确
        if (dimension.content) {
          // 移除html标签后计算纯文本长度
          const contentText = dimension.content.replace(/<[^>]*>?/gm, '')
          // 更保守的估计
          height += Math.min(200, (contentText.length / 150) * 15) // 限制最大高度估计，每150字符15mm
        }

        // 图表 - 降低估计高度
        if (dimension.hasChart) {
          height += 200 // 更保守的图表高度估计
        }

        return height
      }

      function debugVisibility() {
        console.log('======= 开始调试DOM元素可见性 =======')

        // 检查报告标题和描述
        const titleEl = document.querySelector('#report-title')
        const descEl = document.querySelector('#report-description')
        console.log(
          '报告标题元素:',
          titleEl ? '存在' : '不存在',
          titleEl ? `内容: ${titleEl.textContent}` : '',
        )
        console.log(
          '报告描述元素:',
          descEl ? '存在' : '不存在',
          descEl ? `内容: ${descEl.textContent}` : '',
        )

        // 检查主内容区
        const contentSection = document.querySelector('#report-content-sections')
        console.log(
          '内容区元素:',
          contentSection ? '存在' : '不存在',
          contentSection ? `子元素数量: ${contentSection.children.length}` : '',
        )

        // 检查维度部分
        const dimensions = document.querySelectorAll('.dimension-section')
        console.log('维度部分数量:', dimensions.length)

        dimensions.forEach((dim, index) => {
          if (index < 3) {
            // 只显示前3个，避免输出过多
            const style = window.getComputedStyle(dim)
            console.log(
              `维度 ${index + 1}:`,
              `ID=${dim.id}`,
              `可见性=${style.display !== 'none' && style.visibility !== 'hidden'}`,
              `透明度=${style.opacity}`,
              `变换=${style.transform}`,
              `类名=${dim.className}`,
            )
          }
        })

        console.log('======= 调试结束 =======')
      }

      // 页面加载后执行调试
      document.addEventListener('DOMContentLoaded', () => {
        // 初始调试
        setTimeout(debugVisibility, 500)

        // API加载完成后再次调试
        setTimeout(debugVisibility, 2000)
      })

      // 新增打印功能，优化打印行为
      function printReport() {
        // 检查是否处于页面视图模式
        const isPageView = document.body.classList.contains('page-view-mode')
        // 记录原始状态
        const originalViewMode = isPageView

        if (!isPageView) {
          // 自动切换到页面视图模式进行打印
          document.body.classList.add('page-view-mode')
          convertToPageView()
          // 给DOM时间更新
          setTimeout(() => {
            // 添加打印专用的class
            document.body.classList.add('print-mode')
            window.print()
            // 打印完成后恢复原始模式
            setTimeout(() => {
              document.body.classList.remove('print-mode')
              if (!originalViewMode) {
                document.body.classList.remove('page-view-mode')
                revertToNormalView()
              }
            }, 500)
          }, 500)
        } else {
          // 如果已经是页面视图模式，添加打印专用class然后打印
          document.body.classList.add('print-mode')
          window.print()
          setTimeout(() => {
            document.body.classList.remove('print-mode')
          }, 500)
        }
      }
    </script>
  </body>
</html>
